/***************************************************************************
 *   Copyright (C) 2016 by telink							               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 ***************************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "tlink_usb.h"
#include "usbprn.h"
#include "cmdfunc.h"

// modify to Makefile later
#define VERSION_STRING			"OCD-0.5-beta"

#define CMDS_MAX_ARGC 			64
#define CMDS_MAX_ARG_LENGTH 	36
#define CMDS_MAX_CMD_LENGTH 	36

int CMDS_Exec (char * cmdline);
int CMDS_Exec_Single (char * cmdline);

char cmdbuf[4*4*1024];
extern libusb_device_handle *tlink_dev;
extern libusb_context *ctx;

int uart_mode;

int MainTask (char * str)
{
	uart_mode = 0;

	strcpy (cmdbuf, str);

	if (strlen (cmdbuf) > 0) {
		if (! CMDS_Exec(cmdbuf) ) 
			return 0;
	}
	else
		CMDS_Exec_Single ("nocmd");

	return 1;
}

int CMDS_Exec (char * cmdline)
{

	char* pstr = cmdline;

	int ret = 1;
	int stop = 0;

	do {
		while ((*pstr==' ' || *pstr=='\t' || *pstr==';' ||
			*pstr=='\r' || *pstr=='\n') && * pstr != '\0') 
			pstr++;
		char * ps = pstr;

		while (*pstr!=';' && *pstr != '\0') 
			pstr++;

		if (*pstr == '\0') 
			stop = 1;

		if (*ps!='\0') {

			*pstr='\0';

 			if (*ps == '-') {
			//we need "nocmd " as start
				memmove (cmdbuf+6, ps,strlen(ps));
				memmove(cmdbuf,"nocmd ",6);
				
				ret = CMDS_Exec_Single (cmdbuf);
			}
			else
				ret = CMDS_Exec_Single (ps);

			if (stop)	
				return ret;
			else		
				pstr++;
		}
		else {
			return 1;
		}
	} while (ret);

	return 0;
}

int CMDS_Exec_Single (char * cmdline)
{

	int i;
	int ret;
	int argc = 0;
	char* argv[CMDS_MAX_ARGC];
	char* pstr = cmdline;
	char * pStrCmd;

	LOG_DEBUG("cmdline %s", cmdline);

	for (i=0; i<CMDS_MAX_ARGC; i++) 
		argv[i] = cmdline + strlen (cmdline);

	// skip leading blanks
	while (*pstr == ' ' && * pstr != '\0')	
		pstr++;

	pStrCmd = pstr;
	int loop = 1;

	while (loop)	{
		if (argc>0 && *pstr == '"') {
			argv[argc-1]++;
			pstr++;
			while (*pstr != '"' && *pstr != '\0')	
				pstr++;
		}
		else {
			while (*pstr != ' ' && *pstr != '\0')	
				pstr++;
		}
		if (*pstr) {
			*pstr++ = '\0';
			while (*pstr == ' ') 
				pstr++;
			argv[argc++] = pstr;
		}
		else
			loop = 0;
	}

	if ((argc > 0) && !(*argv[argc-1]))
		argc--;

	if (strcmp(pStrCmd, "") != 0) 
		ret = Cmd_Process (pStrCmd, argc, argv);
	else
		ret = ERROR_FAIL;

	return ret;
}


#if defined(STANDALONE)
int main(int argc, const char * argv[])
{

	char str[1024];
	int i, n = 0;

	LOG_INFO("[version %s]", VERSION_STRING);

	for (i = 1; i < argc; i++)
	{
		int l = strlen (argv[i]);
		memcpy (str + n, argv[i], l);
		str[n + l] = ' ';
		n += l + 1;
	}
	str[n] = 0;

	if (GetHandle () == ERROR_OK) {
		MainTask (str);
	}
	else{
		LOG_USER("USB open failed");
	}

	tlink_usb_close();//clean up
	return ERROR_OK;
}

#else
// we are using the same USB handle from openocd
int tcdb_main(libusb_device_handle * devh, int argc, const char * argv[])
{

	char str[1024];
	int i, n = 0;

	if (devh != NULL)
		tlink_dev = devh;
	else
		return ERROR_FAIL;

	// OpenOCD argument passing is completely diff.   the 0 is the first arg
	for (i = 0; i < argc; i++)
	{
		int l = strlen (argv[i]);
		memcpy (str + n, argv[i], l);
		str[n + l] = ' ';
		n += l + 1;
	}
	str[n] = 0;

	MainTask (str);

	LOG_DEBUG("done tcdb cmd");

	return ERROR_OK;
}

#endif // ALONE


